package com.logger;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;

import com.fmk.utils.RegExpUtils;
import com.logger.query.QueryFormatter;

public class LogQuery {

    private Date                 dateTime;
    private String               queryfile;
    private String               queryname;
    private StringBuilder        queryContent;
    private long                 constructionTime;
    private long                 executionTime;
    private long                 rowsNumber;
    private final LogFile        logFile;
    private final LogTransaction transaction;
    private String               msgError;

    public LogQuery(final LogFile logFile) {
        this(logFile, null);
    }

    public LogQuery(final LogFile logFile, final LogTransaction transaction) {
        this.rowsNumber = -1;
        this.executionTime = -1;
        this.logFile = logFile;
        if (this.logFile != null) {
            this.logFile.getListLogQuery().add(this);
        }
        this.transaction = transaction;
        if (this.getTransaction() != null) {
            this.getTransaction().getQueries().add(this);
        }
    }

    public LogQuery init(final String line) {
        this.dateTime = LogQuery.setDateTime(line);
        this.queryfile = LogQuery.setFileName(line);
        this.queryname = LogQuery.setQueryName(line);
        return this;
    }

    public boolean isInitialized() {
        return this.dateTime != null;
    }

    public static String setQueryName(final String line) {
        final Matcher matcher = RegExpUtils.createMatcher(line, RegExpUtils.Constants.REGX_QUERY_NAME);
        if (matcher.find()) {
            final String group = matcher.group(1);
            final String replace = group.replace(".", "").replace("]", "");
            return replace;
        } else {
            return "UNKNOWN";
        }
    }

    public static String setFileName(final String line) {
        final Matcher matcher = RegExpUtils.createMatcher(line, RegExpUtils.Constants.REGX_FILE_NAME);
        if (matcher.find()) {
            final String group = matcher.group(1);
            final String replace = group.replace("[", "").replace(".", "");
            return replace;
        } else {
            return "UNKNOWN";
        }
    }

    public static Date setDateTime(final String line) {
        final Matcher matcher = RegExpUtils.createMatcher(line, RegExpUtils.Constants.REGX_DATE_TIME);
        if (matcher.find()) {
            final String dateTime = matcher.group(1);
            final SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
            final ParsePosition pos = new ParsePosition(0);
            pos.setIndex(0);
            final Date parse = parser.parse(dateTime, pos);
            return parse;
        }
        return null;
    }

    public Date getDateTime() {
        return this.dateTime;
    }

    public String getQueryfile() {
        return this.queryfile;
    }

    public String getQueryName() {
        return this.queryname;
    }

    public StringBuilder getQueryContent() {
        if (this.queryContent == null) {
            this.queryContent = new StringBuilder();
        }
        return this.queryContent;
    }

    public String getRawQueryContent() {
        return QueryFormatter.getRawQuery(this.queryContent);
    }

    public String getRawQueryContentPreview() {
        return QueryFormatter.getPreview(this.queryContent);
    }

    public Long getConstructionTime() {
        return this.constructionTime;
    }

    public void setConstructionTime(final Long constructionTime) {
        this.constructionTime = constructionTime;
    }

    public void setConstructionTime(final String line) {
        final String replacement = "";
        String newLine = line.replaceFirst(RegExpUtils.Constants.REGX_REPLACE_SQL_CONSTRUCTION_TIME_BEG, replacement);
        newLine = newLine.replaceFirst(RegExpUtils.Constants.REGX_REPLACE_SQL_TIME_END, replacement);
        if (line.equals(newLine)) {
            return;
        }
        final Long _constructionTime = new Long((long) (Double.valueOf(newLine) * 1000));
        this.setConstructionTime(_constructionTime);
    }

    public long getExecutionTime() {
        return this.executionTime;
    }

    private void setExecutionTime(final long executionTime) {
        this.executionTime = executionTime;
    }

    public void setRowsNumber(final String line) {
        final String replacement = "";
        String newLine = line.replaceFirst(RegExpUtils.Constants.REGX_REPLACE_ROWS_NUMBER_AFFECTED_BEGIN, replacement);
        newLine = newLine.replaceFirst(RegExpUtils.Constants.REGX_REPLACE_ROWS_NUMBER_AFFECTED_END, replacement);

        if (line.equals(newLine)) {
            return;
        }
        final long _rowsNumber = Long.parseLong(newLine);
        this.setRowsNumber(_rowsNumber);
    }

    public void setElapsedTime(final String line) {
        final String replacement = "";
        String newLine = line.replaceFirst(RegExpUtils.Constants.REGX_REPLACE_SQL_EXECUTION_ELAPSED_TIME, replacement);
        newLine = newLine.replaceFirst(RegExpUtils.Constants.REGX_REPLACE_SQL_TIME_END, replacement);

        if (line.equals(newLine)) {
            return;
        }
        final long _executionTime = (long) (Double.valueOf(newLine) * 1000);
        this.setExecutionTime(_executionTime);
    }

    public long getRowsNumber() {
        return this.rowsNumber;
    }

    private void setRowsNumber(final long rowsNumber) {
        this.rowsNumber = rowsNumber;
    }

    public LogFile getLogFile() {
        return this.logFile;
    }

    public static boolean isFirstQueryName(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_REQUEST_PREPARE_QUERY_NAME;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;

    }

    public static boolean isSecondQueryName(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_INFO_REQUEST_EXECUTE_QUERY;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;
    }

    public static boolean isSQLConstructionTime(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_CONSTRUCTION_TIME;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;
    }

    public static boolean isSQLRowsNnumberElapsedTime(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_ROWS_NUMBER_ELAPSED_TIME;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;
    }

    public static boolean isRowsNnumber(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_ROWS_NUMBER_2;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;
    }

    public static boolean isRowsAffected(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_ROWS_NUMBER_AFFECTED;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;
    }

    public static boolean isElapsedTime(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_ELAPSED_TIME;
        final boolean match = RegExpUtils.isMatchFound(line, _regularExp);
        return match;
    }

    public static boolean isRawQuery(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_RAW_QUERY;
        return RegExpUtils.isMatchFound(line, _regularExp);
    }

    // public static boolean isSequancesQuery(final String line) {
    // final String _regularExp = REGX_SEQUANCES_QUERY;
    // return match(line, _regularExp);
    // }

    public static boolean isSQLRowsAffectedElapsedTime(final String line) {
        final String _regularExp = RegExpUtils.Constants.REGX_ROWS_AFFECTED_2;
        return RegExpUtils.isMatchFound(line, _regularExp);
    }

    public void setRawQuery(final String line) {
        final String replacement = "";
        final String newLine = line.replaceFirst(RegExpUtils.Constants.REGX_RAW_QUERY, replacement);
        this.getQueryContent().append(newLine);
    }

    public String getMsgError() {
        return this.msgError;
    }

    public void setMsgError(final String msgError) {
        this.msgError = msgError;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(this.queryfile);
        sb.append(".");
        sb.append(this.queryname);
        sb.append("][");
        if (this.getTransaction() != null) {
            sb.append("TransactionId:");
            sb.append(this.getTransaction().getId());
            sb.append("][");
        }
        final String rawQueryContent = this.getRawQueryContentPreview();
        sb.append(rawQueryContent == null || rawQueryContent.equals("") ? "NO CONTENT" : rawQueryContent);
        if (this.executionTime > 40000) {
            sb.append("][");
            sb.append("Execution time:");
            sb.append(Double.valueOf((double) this.executionTime / 1000));
        }
        sb.append("]");
        return sb.toString();
    }

    public LogTransaction getTransaction() {
        return this.transaction;
    }
}
